package health

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"sync"

	v1 "fiberx/api/health/v1"
	"fiberx/internal/utils"

	"github.com/gofiber/fiber/v3"
	"github.com/shirou/gopsutil/v3/cpu"
	"github.com/shirou/gopsutil/v3/disk"
	"github.com/shirou/gopsutil/v3/mem"
	"golang.org/x/sys/unix"
)

func (h *Health) HealthCheck(c fiber.Ctx) (res *v1.HealthCheckRes, err error) {
	var (
		cpuPercent                                   []float64
		memInfo                                      *mem.VirtualMemoryStat
		diskInfo                                     *disk.UsageStat
		goroutineNum                                 int
		loadAvg                                      []float64
		cpuInfo                                      []cpu.InfoStat
		wg                                           sync.WaitGroup
		cpuErr, memErr, diskErr, loadErr, cpuInfoErr error
		osInfo                                       unix.Utsname
		totalDisk                                    uint64
	)

	// 并行获取各项系统信息
	wg.Add(6)
	go func() {
		defer wg.Done()
		// 非阻塞获取 CPU 使用率
		cpuPercent, cpuErr = cpu.Percent(0, false)
	}()
	go func() {
		defer wg.Done()
		memInfo, memErr = mem.VirtualMemory()
	}()
	go func() {
		defer wg.Done()
		diskInfo, diskErr = disk.Usage("/")
		if diskErr == nil {
			totalDisk = diskInfo.Total
		}
	}()
	go func() {
		defer wg.Done()
		sysinfo := &unix.Sysinfo_t{}
		loadErr = unix.Sysinfo(sysinfo)
		if loadErr == nil {
			loadAvg = []float64{
				float64(sysinfo.Loads[0]) / 65536.0,
				float64(sysinfo.Loads[1]) / 65536.0,
				float64(sysinfo.Loads[2]) / 65536.0,
			}
		}
	}()
	go func() {
		defer wg.Done()
		cpuInfo, cpuInfoErr = cpu.Info()
	}()
	go func() {
		defer wg.Done()
		err := unix.Uname(&osInfo)
		if err != nil {
			return
		}
	}()

	// 等待所有 goroutine 完成
	wg.Wait()

	// 检查是否有错误
	if cpuErr != nil {
		return nil, cpuErr
	}
	if memErr != nil {
		return nil, memErr
	}
	if diskErr != nil {
		return nil, diskErr
	}
	if loadErr != nil {
		return nil, loadErr
	}
	if cpuInfoErr != nil {
		return nil, cpuInfoErr
	}

	// 获取逻辑核数（直接使用总核心数）
	logicalCores := len(cpuInfo)

	// 计算物理核数（通过 Socket 和 CoreID 去重，忽略超线程）
	physicalCores := make(map[string]bool)
	for _, info := range cpuInfo {
		// 组合 Socket 和 CoreID 作为唯一标识（不同系统字段可能略有差异）
		key := fmt.Sprintf("%s-%s", info.PhysicalID, info.CoreID)
		physicalCores[key] = true
	}

	// 获取运行频率（取第一个核心的当前频率，单位为 MHz）
	var currentFreqMHz string
	if len(cpuInfo) > 0 {
		currentFreqMHz = fmt.Sprintf("%.f MHz", cpuInfo[0].Mhz)
	}

	// 获取 goroutine 数量
	goroutineNum = runtime.NumGoroutine()

	// 格式化负载等信息为保留两位小数的百分比形式
	formattedCPUUsage := fmt.Sprintf("%.2f%%", cpuPercent[0])
	formattedMemoryUsage := fmt.Sprintf("%.2f%%", memInfo.UsedPercent)
	formattedDiskUsage := fmt.Sprintf("%.2f%%", diskInfo.UsedPercent)
	formattedLoadAvg := make([]string, len(loadAvg))
	for i, load := range loadAvg {
		formattedLoadAvg[i] = fmt.Sprintf("%.2f%%", load)
	}

	cpuModel := ""
	if len(cpuInfo) > 0 {
		cpuModel = cpuInfo[0].ModelName
	}

	totalMemory := float64(memInfo.Total) / (1024 * 1024 * 1024)
	formattedTotalMemory := fmt.Sprintf("%.f GB", totalMemory)

	totalDiskGB := float64(totalDisk) / (1024 * 1024 * 1024)
	formattedTotalDisk := fmt.Sprintf("%.f GB", totalDiskGB)

	osName := strings.TrimRight(string(osInfo.Sysname[:]), "\x00")
	kernelVersion := strings.TrimRight(string(osInfo.Release[:]), "\x00")
	platform := runtime.GOOS

	switch platform {
	case "linux":
		if content, err := os.ReadFile("/etc/os-release"); err == nil {
			lines := strings.Split(string(content), "\n")
			for _, line := range lines {
				if strings.HasPrefix(line, "PRETTY_NAME=") {
					parts := strings.SplitN(line, "=", 2)
					if len(parts) == 2 {
						platform = strings.Trim(parts[1], "\"")
					}
					break
				}
			}
		}
	case "windows":
		cmd := exec.Command("wmic", "os", "get", "Caption")
		output, err := cmd.Output()
		if err == nil {
			scanner := bufio.NewScanner(strings.NewReader(string(output)))
			for scanner.Scan() {
				line := strings.TrimSpace(scanner.Text())
				if line != "" && line != "Caption" {
					platform = line
					break
				}
			}
		}
	case "darwin":
		cmd := exec.Command("sw_vers", "-productName", "-productVersion")
		output, err := cmd.Output()
		if err == nil {
			parts := strings.Fields(string(output))
			if len(parts) >= 2 {
				platform = fmt.Sprintf("%s %s", parts[0], parts[1])
			}
		}
	}

	// 构建响应
	response := &v1.HealthCheckRes{
		OS:             osName,
		Kernel:         kernelVersion,
		Platform:       platform,
		CPUModel:       cpuModel,
		LogicalCores:   logicalCores,
		PhysicalCores:  len(physicalCores),
		CurrentFreqMHz: currentFreqMHz,
		TotalMemory:    formattedTotalMemory,
		TotalDisk:      formattedTotalDisk,
		CPUUsage:       formattedCPUUsage,
		MemoryUsage:    formattedMemoryUsage,
		DiskUsage:      formattedDiskUsage,
		GoroutineNum:   goroutineNum,

		LoadAverage: formattedLoadAvg,
		Time:        utils.T.FormatAsYYYYMMDDHHMMSS(),
	}

	return response, nil
}
